package com.cloudbroker.bcs.platform.ltb.middle.aspect;
import com.cloudbroker.bcs.common.annotation.RedisMutex;
import com.cloudbroker.bcs.platform.ltb.common.util.CacheHelper;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Method;
import java.util.UUID;

/**
 * Created by tianrui on 2016/8/23.
 */
public class RedisAspect {

    private static final Logger LOGGER = LoggerFactory.getLogger(RedisAspect.class);

    public Object redisOperator(ProceedingJoinPoint pjp) throws Throwable {
        //通过分析aop监听参数分析出request等信息
        // 在Spring的环境里，signature就是MethodSignature
        Object result = null;
        MethodSignature methodSignature = (MethodSignature) pjp.getSignature();
        // 获取Method
        Method method = methodSignature.getMethod();
        if (method.isAnnotationPresent(RedisMutex.class)){
            RedisMutex redisMutex = method.getAnnotation(RedisMutex.class);
            if (StringUtils.isBlank(redisMutex.key())){
                LOGGER.error("redis key not be empty");
                throw new Exception("redis key not be empty");
            }
            CacheHelper cacheHelper = CacheHelper.getInstance();
            String uuid = UUID.randomUUID().toString();
            try{
                while (true) {
                    Long lock = cacheHelper.setnx(redisMutex.key(), uuid, redisMutex.expireTime());
                    if (lock != 0) {
                        break;
                    }
                    try {
                        //100ms拿一次锁
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                result = pjp.proceed();
            }catch (Exception e){
                LOGGER.error("execute failed", e);
            }finally {
                if(cacheHelper.get(redisMutex.key()) != null && cacheHelper.get(redisMutex.key()).equals(uuid)){
                    cacheHelper.delete(redisMutex.key());
                }
            }
            return result;
        }else {
            return pjp.proceed();
        }

    }

}
